package com.bsj.power.pls.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.bsj.power.common.config.global.JsonResult;
import com.bsj.power.common.config.global.JsonResultEnum;
import com.bsj.power.common.constant.NumericalConstants;
import com.bsj.power.common.def.dto.tree.TreeDTO;
import com.bsj.power.common.def.entity.Scene;
import com.bsj.power.common.def.entity.locationDevice.LocationDevice;
import com.bsj.power.common.def.entity.tree.Tree;
import com.bsj.power.common.def.vo.tree.TreeStructureVO;
import com.bsj.power.common.def.vo.tree.TreeVO;
import com.bsj.power.common.mapper.LocationDeviceMapper;
import com.bsj.power.common.mapper.TreeMapper;
import com.bsj.power.common.util.ParamCheckUtil;
import com.bsj.power.pls.service.TreeService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author LiJiaXin
 * @version 1.0.0
 * @description TreeServiceImpl
 * @time 2024/10/9 11:50
 */
@Service
public class TreeServiceImpl implements TreeService {

    @Resource
    private TreeMapper treeMapper;

    @Resource
    private LocationDeviceMapper locationDeviceMapper;

    /**
     * 添加
     *
     * @param treeDTO
     * @return com.bsj.power.common.config.global.JsonResult
     * @author ljx
     * @time 2024/10/9 14:02
     */
    @Override
    @Transactional
    public JsonResult addTree(TreeDTO treeDTO) {
        Integer parentId = treeDTO.getParentId();
        if (!parentId.equals(NumericalConstants.NEGATIVE_ONE)) {
            ParamCheckUtil.isNull(treeMapper.selectById(parentId));
        }
        Tree tree = new Tree();
        BeanUtils.copyProperties(treeDTO, tree);
        if (treeMapper.insert(tree) > NumericalConstants.ZERO) {
            return JsonResult.success();
        } else {
            return JsonResult.fail();
        }
    }

    /**
     * 删除
     *
     * @param treeId
     * @return com.bsj.power.common.config.global.JsonResult
     * @author ljx
     * @time 2024/10/9 14:02
     */
    @Override
    @Transactional
    public JsonResult deleteTree(Integer treeId) {
        ParamCheckUtil.isNull(treeId);
        ParamCheckUtil.isNull(treeMapper.selectById(treeId), JsonResultEnum.TREE_BRANCH_ISNULL);
        if (treeMapper.exists(Wrappers.<Tree>lambdaQuery().eq(Tree::getParentId, treeId))) {
            return JsonResult.fail(JsonResultEnum.EXIST_SON_BRANCH);
        }
        if (locationDeviceMapper.exists(Wrappers.<LocationDevice>lambdaQuery().eq(LocationDevice::getTreeId, treeId))) {
            return JsonResult.fail(JsonResultEnum.IS_BINDING_BASE_STATION);
        }
        if (treeMapper.deleteById(treeId) > NumericalConstants.ZERO) {
            return JsonResult.success();
        } else {
            return JsonResult.fail();
        }
    }

    /**
     * 修改
     *
     * @param treeDTO
     * @return com.bsj.power.common.config.global.JsonResult
     * @author ljx
     * @time 2024/10/9 14:02
     */
    @Override
    @Transactional
    public JsonResult updateTree(TreeDTO treeDTO) {
        Integer treeId = treeDTO.getTreeId();
        ParamCheckUtil.isNull(treeId);
        Tree oldTree = treeMapper.selectById(treeId);
        ParamCheckUtil.isNull(oldTree);
        if (oldTree.getParentId().equals(NumericalConstants.NEGATIVE_ONE)) {
            return JsonResult.fail(JsonResultEnum.CANNOT_CHANGE_PARENT);
        }
        List<Integer> treeIds = getTreeIds(treeId, NumericalConstants.TWO);
        if (!CollectionUtils.isEmpty(treeIds)) {
            //上级不能为本身或子集中任意一个
            if (treeIds.contains(treeDTO.getParentId())) {
                return JsonResult.fail(JsonResultEnum.PARENT_DIRECTORY_ERROR);
            }
        }
        Tree tree = new Tree();
        BeanUtils.copyProperties(treeDTO, tree);
        LambdaUpdateWrapper<Tree> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.eq(Tree::getTreeId, treeId);
        if (StringUtils.isBlank(tree.getRemark())) {
            updateWrapper.set(Tree::getRemark, null);
        }
        if (treeMapper.update(tree, updateWrapper) > NumericalConstants.ZERO) {
            return JsonResult.success();
        } else {
            return JsonResult.fail();
        }
    }

    /**
     * 获取单个
     *
     * @param treeId
     * @return com.bsj.power.common.def.vo.tree.TreeVO
     * @author ljx
     * @time 2024/10/9 14:02
     */
    @Override
    public TreeVO getTreeById(Integer treeId) {
        ParamCheckUtil.isNull(treeId);
        Tree tree = treeMapper.selectById(treeId);
        ParamCheckUtil.isNull(tree, JsonResultEnum.TREE_BRANCH_ISNULL);
        TreeVO treeVO = new TreeVO();
        BeanUtils.copyProperties(tree, treeVO);
        return treeVO;
    }

    /**
     * 树结构
     *
     * @return java.util.List<com.bsj.power.common.def.vo.tree.TreeStructureVO>
     * @author ljx
     * @time 2024/10/9 14:02
     */
    @Override
    public List<TreeStructureVO> getTreeStructure() {
        return null;
    }

    /**
     * 获取当前目录的所有下级或上级目录id（包括本身）
     *
     * @param treeId
     * @param type   1:上级 2:下级
     * @return java.util.List<java.lang.Integer>
     * @author ljx
     * @time 2024/10/14 10:58
     */
    @Override
    public List<Integer> getTreeIds(Integer treeId, Integer type) {
        Set<Integer> set = new HashSet<>();
        Set<Integer> treeIds = new HashSet<>();
        set.add(treeId);
        treeIds.add(treeId);
        if (type == 1) {
            getSuUId(set, treeIds);
        } else {
            getLoUId(set, treeIds);
        }
        return set.stream().collect(Collectors.toList());
    }

    /**
     * 获取下级目录id
     *
     * @param set
     * @param treeIds
     * @return void
     * @author ljx
     * @time 2024/10/14 11:03
     */
    private void getLoUId(Set<Integer> set, Set<Integer> treeIds) {
        LambdaQueryWrapper<Tree> lambdaQueryWrapper = Wrappers.<Tree>lambdaQuery().in(Tree::getParentId, treeIds).select(Tree::getTreeId);
        List<Tree> treeList = treeMapper.selectList(lambdaQueryWrapper);
        if (!CollectionUtils.isEmpty(treeList)) {
            treeIds.clear();
            for (Tree tree : treeList) {
                Integer treeId = tree.getTreeId();
                set.add(treeId);
                treeIds.add(treeId);
            }
            getLoUId(set, treeIds);
        }
    }

    /**
     * 获取上级目录id
     *
     * @param set
     * @param treeIds
     * @return void
     * @author ljx
     * @time 2024/10/14 11:09
     */
    private void getSuUId(Set<Integer> set, Set<Integer> treeIds) {
        LambdaQueryWrapper<Tree> lambdaQueryWrapper = Wrappers.<Tree>lambdaQuery().in(Tree::getTreeId, treeIds).select(Tree::getParentId);
        List<Tree> treeList = treeMapper.selectList(lambdaQueryWrapper);
        List<Integer> treeIdList = treeList.stream().map(Tree::getParentId).collect(Collectors.toList());
        treeIdList.remove(new Integer(-1));
        if (!CollectionUtils.isEmpty(treeIdList)) {
            treeIds.clear();
            for (Integer treeId : treeIdList) {
                set.add(treeId);
                treeIds.add(treeId);
            }
            getSuUId(set, treeIds);
        }
    }

}
